Skip to content

feat(feedback): Add screenshot attachment button to user feedback widget - #5828

Merged
markushi merged 23 commits into
mainfrom
feat/feedback-screenshot-attachment
Aug 25, 2026
Merged

feat(feedback): Add screenshot attachment button to user feedback widget#5828
markushi merged 23 commits into
mainfrom
feat/feedback-screenshot-attachment

Conversation

@markushi

@markushi markushi commented Jul 23, 2026

Copy link
Copy Markdown
Member

📜 Description

Adds an "Add a screenshot" button to the Android user feedback form that opens the
androidx photo picker (ActivityResultContracts.PickVisualMedia, images only) and sends
the picked image as an attachment in the same envelope as the feedback.

Screen_recording_20260813_202418.mp4
image
  • New SentryFeedbackOptions: enableAttachScreenshot (default true, matching the JS SDK),
    addScreenshotButtonLabel, removeScreenshotButtonLabel, screenshotTooLargeMessageText, plus the
    io.sentry.feedback.enable-attach-screenshot manifest flag
  • androidx.activity:activity:1.8.2 is added as compileOnly — no new transitive
    dependency; the button is hidden (with a warning log) when androidx.activity is missing
    or the host Activity is not a ComponentActivity
  • The image is size-checked against maxAttachmentSize at pick time

Fixed along the way

The form was not scrollable, so in landscape or at large font scales the send and cancel
buttons were pushed off screen and the dialog could not be dismissed. It is now wrapped in
a ScrollView, and the three full width buttons were replaced with the framework dialog
button bar (cancel and send in a right aligned bar, screenshot as a borderless full width
action). No changelog entry, as it is bundled with this feature.

💡 Motivation and Context

💚 How did you test it?

Unit tests + Manual testing.

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

@linear-code

linear-code Bot commented Jul 23, 2026

Copy link
Copy Markdown

JAVA-538

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against dbe756c

@sentry

sentry Bot commented Jul 23, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.53.0 (1) release

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 316.09 ms 390.36 ms 74.28 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
a416a65 333.78 ms 410.37 ms 76.59 ms
2195398 319.02 ms 342.38 ms 23.36 ms
62b579c 349.26 ms 426.26 ms 77.00 ms
bbc35bb 324.88 ms 425.73 ms 100.85 ms
e59e22a 374.68 ms 442.14 ms 67.46 ms
806307f 357.85 ms 424.64 ms 66.79 ms
62b579c 312.88 ms 361.57 ms 48.70 ms
8687935 332.52 ms 362.23 ms 29.71 ms
1edbdfa 364.77 ms 450.29 ms 85.52 ms
2195398 322.52 ms 361.91 ms 39.39 ms

App size

Revision Plain With Sentry Diff
a416a65 1.58 MiB 2.12 MiB 555.26 KiB
2195398 0 B 0 B 0 B
62b579c 0 B 0 B 0 B
bbc35bb 1.58 MiB 2.12 MiB 553.01 KiB
e59e22a 1.58 MiB 2.20 MiB 635.34 KiB
806307f 1.58 MiB 2.10 MiB 533.42 KiB
62b579c 0 B 0 B 0 B
8687935 1.58 MiB 2.19 MiB 619.17 KiB
1edbdfa 1.58 MiB 2.20 MiB 635.34 KiB
2195398 0 B 0 B 0 B

Previous results on branch: feat/feedback-screenshot-attachment

Startup times

Revision Plain With Sentry Diff
86e5409 326.20 ms 351.31 ms 25.11 ms
676848b 367.87 ms 443.02 ms 75.15 ms
e07d37f 355.46 ms 419.13 ms 63.67 ms
f26f131 316.70 ms 333.33 ms 16.63 ms
37c6869 327.68 ms 381.06 ms 53.38 ms
71243e7 313.69 ms 370.22 ms 56.54 ms

App size

Revision Plain With Sentry Diff
86e5409 0 B 0 B 0 B
676848b 0 B 0 B 0 B
e07d37f 0 B 0 B 0 B
f26f131 0 B 0 B 0 B
37c6869 0 B 0 B 0 B
71243e7 0 B 0 B 0 B

@markushi
markushi marked this pull request as ready for review July 23, 2026 17:27
Comment thread sentry/src/main/java/io/sentry/util/FileUtils.java
Comment thread sentry/src/main/java/io/sentry/util/FileUtils.java Outdated

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this!

Comment thread sentry/src/main/java/io/sentry/util/FileUtils.java Outdated
Comment thread sentry-android-core/build.gradle.kts
Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java Outdated
Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java Outdated
markushi added 2 commits July 24, 2026 10:39
Use term "screenshot" everywhere
Improve nullability handling
markushi and others added 2 commits August 12, 2026 12:48
…hment paths

Routes the three catch-all blocks around the screenshot picker through
ExceptionUtils.rethrowIfFatal, so OOM, ThreadDeath and linkage errors
propagate instead of being hidden, and logs the previously silent
failure in getUriSize.

Also moves the androidx.activity availability check out of
SentryFeedbackScreenshotPicker, so the class is only loaded once the
check passed, as its javadoc requires.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
markushi and others added 2 commits August 13, 2026 12:52
… buttons

The form was not scrollable, so in landscape or at large font scales the
send and cancel buttons were pushed off screen and the dialog could not
be dismissed. Wraps it in a ScrollView.

Also replaces the three full width buttons with the framework dialog
button bar: cancel and send sit in a right aligned bar, and the
screenshot button becomes a borderless full width action.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…istration

ActivityResultRegistry.registerKey returns early for a key that is already
registered, so re-registering would not have thrown.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@markushi
markushi requested a review from runningcode August 13, 2026 18:25
@markushi markushi added the sanity-check PR needs a lightweight review for obvious issues label Aug 13, 2026
markushi and others added 2 commits August 13, 2026 20:54
…hot-attachment

# Conflicts:
#	CHANGELOG.md
#	sentry-android-core/src/main/java/io/sentry/android/core/SentryUserFeedbackForm.java
#	sentry-android-core/src/test/java/io/sentry/android/core/SentryUserFeedbackFormTest.kt
#	sentry/api/sentry.api
#	sentry/src/main/java/io/sentry/SentryFeedbackOptions.java
#	sentry/src/main/java/io/sentry/SentryOptions.java
#	sentry/src/test/java/io/sentry/SentryFeedbackOptionsTest.kt
…ed types

AGENTS.md now forbids new catch (Throwable). Replaces the three broad
catches with the types the guarded code can actually throw:

- launch() documents ActivityNotFoundException and the registry throws
  IllegalStateException for an unregistered launcher
- the ContentResolver calls cross into the provider process, where Binder
  can only deliver the exceptions Parcel marshals, all RuntimeException

Fatal throwables now propagate because they are never caught, so
ExceptionUtils.rethrowIfFatal is no longer needed here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 5edad4a. Configure here.

androidx.activity is a compileOnly dependency, so the version in the app's
apk is outside our control and may be missing the photo picker APIs this
was compiled against. Catches LinkageError locally at the two call sites
that link against it, then falls back to the sanctioned
ExceptionUtils.rethrowIfFatal pattern, as ExceptionUtils documents and
SentrySQLiteDriver.hasConnectionPool demonstrates.

Registration is now guarded too, so a version mismatch hides the
screenshot button instead of breaking the whole form.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks better! i think we can simplify the stuff around calling the picker!

Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java
Comment thread sentry/src/main/java/io/sentry/util/FileUtils.java
Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java Outdated
Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java Outdated
Comment thread sentry/src/main/java/io/sentry/SentryFeedbackOptions.java Outdated

@romtsn romtsn left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice work!

runningcode and others added 4 commits August 24, 2026 12:49
* docs(agents): Remove duplicated build commands and rules

AGENTS.md is force-read at the start of every session, so anything stated
there costs context on every task. Several rules had accumulated multiple
copies of themselves within that one file.

`spotlessApply`/`apiDump` was stated five times in AGENTS.md; it is now
stated once as a command and once as a workflow step, with the underlying
facts (Spotless enforces formatting, `.api` files are generated) kept where
they belong. The Testing command block is dropped in favour of the `test`
skill, which already resolves the per-module task and the unit-vs-system
split and does not drift. The Repository Skills bullet list restated skill
descriptions that the harness already injects, so it is now a pointer.

In the rules, `new_module.mdc`'s "Important Notes" was a verbatim
restatement of the AGENTS.md contributing guidelines, and `api.mdc` repeated
the opt-in-by-default rule in passing; both now defer to their canonical
homes.

No guidance is lost — every removed line is still stated somewhere that is
loaded when it applies.

* docs(agents): Refresh new_module rule and cover full system-test runs

Validating the previous commit with agents surfaced two gaps.

`new_module.mdc` had drifted from the repo. Its README badge snippet still
used the retired maven-badges.herokuapp.com format, while every current row
in README.md uses shields.io with a central.sonatype.com link. It also never
mentioned four steps that every existing integration module performs: the
`SENTRY_*_SDK_NAME` constant in `Config.kt` consumed by buildConfig and the
jar manifest, the `libs.versions.toml` entry paired with a `compileOnly`
dependency, self-registration via `SentryIntegrationPackageStorage.addPackage`
and `addIntegrationToSdkVersion`, and the integrations dropdown in the issue
template. It now also points at `sentry-kafka` and `sentry-android-timber` as
build-script templates, and records that `sentry-bom` and the root build file
need no change because they iterate over subprojects.

The `test` skill only ever ran a single module, so folding the AGENTS.md
testing block into it dropped the only reference to running the whole system
test suite. Step 3b now covers `make systemTest` and `make systemTestInteractive`.
* perf(android): Use build-time manifest metadata

Allow the Android Gradle plugin to provide authoritative manifest metadata so SDK initialization can skip PackageManager and Bundle unparceling. Read the injected map directly to avoid conversion overhead.

Refs JAVA-531
Co-Authored-By: Codex <noreply@openai.com>

* changelog

* ref(android): Store metadata in manifest reader

Use ManifestMetadataReader directly as the Gradle plugin injection target and remove the dedicated holder class.

Co-Authored-By: OpenAI Codex <noreply@openai.com>

* docs: Generalize performance changelog entry

Remove the device-specific benchmark percentage from the release note.

Co-Authored-By: Codex <noreply@openai.com>

* docs: Update replacement PR changelog link

Point the performance entry at the replacement pull request.

Co-Authored-By: Codex <noreply@openai.com>

---------

Co-authored-by: Codex <noreply@openai.com>
@markushi
markushi merged commit 1321b40 into main Aug 25, 2026
70 of 71 checks passed
@markushi
markushi deleted the feat/feedback-screenshot-attachment branch August 25, 2026 12:24
buenaflor pushed a commit that referenced this pull request Aug 25, 2026
…get (#5828)

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Nelson Osacky <nelson.osacky@sentry.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

sanity-check PR needs a lightweight review for obvious issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add file attachment support to user feedback widget

3 participants